﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DBSourceToolsLib
{
    public class ZipWriter : Interfaces.IProgressEvent //, Interfaces.ISourceDatabaseCommand
    {
        private string m_strZipFileName = "";
        private string m_strProjectFileName = "";
        private string m_strDeploymentTargetNickName = "";
        DatabaseProject m_DatabaseProject = null;
        FileUtils m_FileUtils = new FileUtils();
        private string m_strSourceDatabaseNick = "";
        private DatabaseEx m_SourceDatabaseEx = null;
        private DatabaseEx m_TargetDatabaseEx = null;
        public event EventHandler<Ionic.Zip.AddProgressEventArgs> AddProgress;
        private int m_ZipFileCount = 0;
        Form m_ParentForm;

        
        public ZipWriter(string strZipFileName)
        {
            m_strZipFileName = strZipFileName;
        }

        public bool WriteZipFile()
        {
            if (m_SourceDatabaseEx == null)
                throw new Exception("Call SetSourceDatabaseNickName before writing");
            if (m_TargetDatabaseEx == null)
                throw new Exception("Call SetTargetDatabaseNick before writing");
            if (UserSettings.Instance().StartupPath == null)
                throw new Exception("Set UserSettings.Instance().StartupPath before writing");
            
            m_FileUtils.EnsureFileDirectoryExists(m_strZipFileName);
            m_FileUtils.DeleteFile(m_strZipFileName);

            m_ZipFileCount = CountFilesInZip();
            string strStartPath = UserSettings.Instance().StartupPath;

            // create temp files.
            string strTempBatchFile = CreateTempBatchFile();

            using (Ionic.Zip.ZipFile oZipFile = new Ionic.Zip.ZipFile(m_strZipFileName))
            {
                oZipFile.AddProgress += new EventHandler<Ionic.Zip.AddProgressEventArgs>(oZipFile_AddProgress);
                
                oZipFile.AddFile(strTempBatchFile,".");
                oZipFile.AddFile(m_DatabaseProject.ProjectFileName, ".");

                oZipFile.AddDirectory(m_SourceDatabaseEx.BaseDirectory, m_SourceDatabaseEx.NickName);
                oZipFile.AddDirectory(strStartPath, "bin");

                oZipFile.Save();
            }

            return true;
        }

        void oZipFile_AddProgress(object sender, Ionic.Zip.AddProgressEventArgs e)
        {
            EventHandler<ProgressEventArgs> localHandler = ProgressEventPublisher;
            if (localHandler != null)
            {
                switch (e.EventType)
                {
                    case Ionic.Zip.ZipProgressEventType.Adding_Started:
                        break;
                    case Ionic.Zip.ZipProgressEventType.Adding_AfterAddEntry:
                        localHandler(this, new ProgressEventArgs(e.EntriesTotal, m_ZipFileCount,
                                            "Processing " + e.CurrentEntry.FileName));

                        break;
                    case Ionic.Zip.ZipProgressEventType.Adding_Completed:
                        localHandler(this, new ProgressEventArgs(100, 100,
                                            "Complete"));

                        break;
                }


            }
            if (AddProgress != null)
                AddProgress(sender, e);
        }


        public void SetProjectFile(string strProjectFile)
        {
            m_strProjectFileName = strProjectFile;
            if (!System.IO.File.Exists(strProjectFile))
                throw new Exception("Cannot open project file : " + strProjectFile);
            m_DatabaseProject = new DatabaseProject(strProjectFile);
            m_DatabaseProject.LoadFromDisk(false);
        }

        public void SetSourceDatabaseNickName(string strSourceDatabaseNick)
        {
            m_strSourceDatabaseNick = strSourceDatabaseNick;
            m_SourceDatabaseEx = m_DatabaseProject.GetDatabaseEx(strSourceDatabaseNick);

            if (m_SourceDatabaseEx == null)
                throw new Exception("Source Database Nickname is invalid " + strSourceDatabaseNick);

        }

        public void SetDeploymentTargetNickName(string strDeploymentTargetNickName)
        {
            m_strDeploymentTargetNickName = strDeploymentTargetNickName;
            m_TargetDatabaseEx = m_DatabaseProject.GetDatabaseEx(strDeploymentTargetNickName);

            if (m_TargetDatabaseEx == null)
                throw new Exception("Target Database Nickname is invalid " + strDeploymentTargetNickName);
        }

        private string CreateTempBatchFile()
        {
            string strTempPath = System.IO.Path.GetTempPath();
            strTempPath += m_strDeploymentTargetNickName;
            //string strTempZipFolder 
            m_FileUtils.DeleteDirRecursive(strTempPath);

            // create Create_db.bat in root directory.
            m_FileUtils.EnsureDirectoryExists(strTempPath);
            string strRootBatchFile = strTempPath + "\\Create_" + m_strDeploymentTargetNickName + ".bat";
            FileUtils.EnsureFileIsWriteable(strRootBatchFile);
            using (System.IO.StreamWriter sWriter = new System.IO.StreamWriter(strRootBatchFile))
            {
                sWriter.WriteLine("cd .\\" + m_strSourceDatabaseNick + "\\DeploymentTargets\\" + m_strDeploymentTargetNickName);
                sWriter.WriteLine("call Run_Create_Scripts.bat");
            }

            return strRootBatchFile;
            
        }

        public int CountFilesInZip()
        {
            int iFileCount = m_FileUtils.CountFilesInDir(UserSettings.Instance().StartupPath);
            iFileCount += m_FileUtils.CountFilesInDir(m_SourceDatabaseEx.BaseDirectory);
            iFileCount++; // add one for batch file
            return iFileCount;
        }

        public event EventHandler<ProgressEventArgs> ProgressEventPublisher;

        public void Execute()
        {
            //m_ParentForm = oForm;
            EventHandler<ProgressEventArgs> localHandler = ProgressEventPublisher;
            

            WriteZipFile();

            if (localHandler != null)
                localHandler(this, new ProgressEventArgs(100, 100,
                    "Processing Complete"));

        }


        private List<string> m_ListErrors = new List<string>();
        public bool HasErrors()
        {
            return m_ListErrors.Count > 0;
        }

        public string GetErrorMessage()
        {
            return m_ListErrors.ToString();
        }

        public void RegisterError(string strErrorMessage)
        {
            m_ListErrors.Add(strErrorMessage);
        }

        public void Execute(Form oForm)
        {
            m_ParentForm = oForm;
            UI.Forms.ProgressForm oProgressForm = new DBSourceToolsLib.UI.Forms.ProgressForm();
            oProgressForm.setEventSource(this);
            oProgressForm.ShowDialog(m_ParentForm);
        }
    }
}
